package service

import (
	"common/biz"
	"common/config"
	"common/logs"
	"common/rsa"
	"common/utils"
	"context"
	"core/dao"
	"core/models/db"
	"core/repo"
	"encoding/json"
	"fmt"
	"framework/game"
	"framework/msError"
	"github.com/smartwalle/alipay/v3"
	"hall/pay/entity"
	"hall/pay/service"
	"net/http"
	"net/url"
)

type WalletService struct {
	userDao *dao.UserDao
}

func (s *WalletService) queryWallet(hfUserID string) (*entity.CommonReceive, error) {
	var dataReceive entity.CommonReceive
	data := entity.Pay{
		UserId: hfUserID,
	}
	data.Url = "alse/qry016"
	data = service.PayData(&data)
	Encrypt, errs := rsa.PayVerifyRsa(&data)
	if errs != nil {
		dataReceive.Code = http.StatusCreated
		return &dataReceive, errs
	}
	response, errs := service.PostData("hfPayRequest", Encrypt)
	if response != nil && response.Code != http.StatusOK {
		errs = fmt.Errorf(response.Msg)
		return &dataReceive, errs
	}

	return response, errs
}

func (s *WalletService) VerificationWallet(ctx context.Context, user *db.UserHasOneRealOfWallet) (*db.UserHfWallet, *msError.Error) {
	hfUserID := fmt.Sprintf("S_%d", user.ID)
	//查询钱包状态
	data, err := s.queryWallet(hfUserID)
	if err != nil {
		logs.Error("[userHandler]用户%d err:用户未实名 req=%v,dbErr=%v", user.ID, user, err)
		return nil, biz.RequestDataError
	}
	hfPayResult := service.JsonOrderResultData(data)
	wallet := new(db.UserHfWallet)
	if hfPayResult.RespCode == "C00000" && hfPayResult.AcctInfoList[0].StatFlag == "1" {
		//查询是否有数据
		wallet = &db.UserHfWallet{
			UID:        user.ID,
			UserCustID: hfPayResult.UserCustId,
			AcctID:     hfPayResult.AcctInfoList[0].AcctId,
			UserName:   hfPayResult.UserName,
			IDCard:     hfUserID,
		}
		err = s.userDao.AddWallet(ctx, wallet)
		if err != nil {
			logs.Error("[userHandler]用户%d err:添加钱包数据失败 req=%v,dbErr=%v", user.ID, user, err)
			return nil, biz.SqlError
		}
	}
	return wallet, nil
}

func (s *WalletService) OpenWallet(ctx context.Context, user *db.UserHasOneRealOfWallet) (string, int64, *msError.Error) {
	var hfResult string
	var err error
	hfUserID := fmt.Sprintf("S_%d", user.ID)
	if !user.Real.Status {
		//未支付
		isPay := false
		if user.Real.OrderNo != "" {
			//查询
			orderData := user.Real.OrderNo[6:14]
			request := new(entity.ReturnResAsynchronous)
			request, err = s.OrderQueryWallet(user.Real.OrderNo, orderData)
			if err != nil {
				logs.Error("[userHandler]用户%d WalletInfo err:查询订单失败 req=%v,dbErr=%v", user.ID, user, err)
				return "", 0, biz.SqlError
			}
			if request.TransStat == "P" {
				return "", 0, biz.PayInError
			}
			if request.TransStat == "S" {
				//查询成功 去开户
				isPay = true
			}
			err = s.userDao.AddWalletLog(ctx, &db.WalletPayLog{
				UID:     user.ID,
				OrderNo: user.Real.OrderNo,
				Info:    request.TransStat,
			})
			if err != nil {
				logs.Error("[userHandler]用户%d WalletInfo err:添加钱包操作记录 req=%v,dbErr=%v", user.ID, user, err)
				return "", 0, biz.SqlError
			}
		}
		if isPay {
			//已支付去开户
			hfResult, err = s.createWallet(user.Real.Name, user.Real.IDCard, hfUserID, user.Username)
			if err != nil {
				logs.Error("[userHandler]用户%d WalletInfo err:开户失败 req=%v,dbErr=%v", user.ID, user, err)
				return "", 0, biz.SqlError
			}
			err = s.userDao.UpRealOsStatus(ctx, user.ID)
			if err != nil {
				logs.Error("[userHandler]用户%d WalletInfo err:修改钱包状态失败 req=%v,dbErr=%v", user.ID, user, err)
				return "", 0, biz.SqlError
			}
			user.Real.Status = true
			return hfResult, 605, nil
		} else {
			//生成支付订单
			walletPayOrderID := fmt.Sprintf("Wallet%s%s", utils.TimeOrDateAsYear(0, "", "YmdHis"), utils.MathInviteCode(14))
			hfResult, err = s.payWallet(user.Real.Name, user.Real.IDCard, hfUserID, walletPayOrderID)
			if err != nil {
				logs.Error("[userHandler]用户%d WalletInfo err:支付失败 req=%v,dbErr=%v", user.ID, user, err)
				return "", 0, biz.SqlError
			}
			err = s.userDao.AddWalletLog(ctx, &db.WalletPayLog{
				UID:     user.ID,
				OrderNo: walletPayOrderID,
				Info:    "创建",
			})
			if err != nil {
				logs.Error("[userHandler]用户%d WalletInfo err:添加钱包记录失败 req=%v,dbErr=%v", user.ID, user, err)
				return "", 0, biz.SqlError
			}
			err = s.userDao.UpRealOsOrderNo(ctx, user.ID, walletPayOrderID)
			if err != nil {
				logs.Error("[userHandler]用户%d WalletInfo err:修改钱包状态失败 req=%v,dbErr=%v", user.ID, user, err)
				return "", 0, biz.SqlError
			}
			user.Real.OrderNo = walletPayOrderID
			return hfResult, 604, nil
		}
	} else {
		//已支付
		hfResult, err = s.createWallet(user.Real.Name, user.Real.IDCard, hfUserID, user.Username)
		if err != nil {
			logs.Error("[userHandler]用户%d WalletInfo err:查询余额失败 req=%v,dbErr=%v", user.ID, user, err)
			return "", 0, biz.SqlError
		}
		return hfResult, 605, nil
	}
}

// OrderQueryWallet 订单查询
func (s *WalletService) OrderQueryWallet(OrderId string, OrderDate string) (*entity.ReturnResAsynchronous, error) {
	request := new(entity.ReturnResAsynchronous)
	data := entity.Pay{
		Version: 10,
		//MerCustId: viper.GetString("wallet.mer_cust_id"),
		MerCustId: game.Conf.GameConfig["pay_wallet"]["value"].(map[string]any)["mer_cust_id"].(string),
		OrderId:   OrderId,
		OrderDate: OrderDate, //订单日期
		TransType: "36",
	}
	//data.Url = viper.GetString("wallet.url") + "alse/qry008"
	data.Url = game.Conf.GameConfig["pay_wallet"]["value"].(map[string]any)["url"].(string) + "alse/qry008"
	Encrypt, errs := rsa.PayVerifyRsa(&data)
	if errs != nil {
		return request, errs
	}
	response, errs := service.PostData("hfPayRequest", Encrypt)
	if response.Code != 200 {
		errs = fmt.Errorf(response.Msg)
		return request, errs
	}
	hfPayResult := service.JsonHfResultData(response)
	return &hfPayResult, nil
}

func (s *WalletService) OrderQueryAlipay(ctx context.Context, orderNo string, method string) (*alipay.TradeQueryRsp, error) {
	client, err := service.AliPay(method)
	if err != nil {
		return nil, err
	}
	param := alipay.TradeQuery{
		OutTradeNo: orderNo,
	}
	result, err := client.TradeQuery(ctx, param)
	if err != nil {
		return nil, err
	}
	return result, nil
}

func (s *WalletService) createWallet(userName, idCard, userId, userMobile string) (string, error) {
	data := entity.Pay{
		OrderId:       fmt.Sprintf("Game%s%s", utils.TimeOrDateAsYear(0, "", "YmdHis"), utils.MathInviteCode(14)),
		UserName:      userName,
		MarketType:    "2",
		AcctUsageType: "wallet", //买卖钱包户
		IdCard:        idCard,
		IdCardType:    10,
		UserId:        userId,
		UserMobile:    userMobile,
		Extension:     "create_wallet",
		MerPriv:       userId, //商户私有
	}
	data.Url = "hfpwallet/w00003"
	data = service.PayData(&data)
	Encrypt, errs := rsa.PayVerifyRsa(&data)
	if errs != nil {
		return "", errs
	}
	response, errs := service.PostData("hfPayRequest", Encrypt)
	if response.Code != 200 {
		errs = fmt.Errorf(response.Msg)
		return "", errs
	}
	hfPayResult := service.JsonHfResultData(response)
	if hfPayResult.RespCode == "C00000" {
		return hfPayResult.RedirectUrl, nil
	} else {
		errs = fmt.Errorf(hfPayResult.RespDesc)
		return "", errs
	}
}

func (s *WalletService) payWallet(userName, idCard, userId, orderId string) (string, error) {
	payMoney := fmt.Sprintf("%.2f", float32(2)) //开户金额
	divDetails := entity.DivDetails{
		DivCustId:   game.Conf.GameConfig["pay_wallet"]["value"].(map[string]any)["mer_cust_id"].(string),
		DivAcctId:   game.Conf.GameConfig["pay_wallet"]["value"].(map[string]any)["div_acct_id"].(string),
		DivAmt:      payMoney,
		RiskDivType: 1,
	}
	var divDetailsArr []entity.DivDetails
	divDetailsArr = append(divDetailsArr, divDetails)
	divDetailsJson, _ := json.Marshal(divDetailsArr)
	object_info, _ := json.Marshal(entity.ObjectInfo{
		MarketType: 1,
	})
	data := entity.Pay{
		OrderId:    orderId,
		UserName:   userName,
		IdCardType: 10,
		IdCard:     idCard,
		DivType:    0,
		DivDetails: string(divDetailsJson),
		TransAmt:   payMoney,
		Extension:  "wallet_pay",
		GoodsDesc:  "开户",
		ObjectInfo: string(object_info),
		UserId:     userId,
		MerPriv:    userId, //商户私有
	}
	data.Url = "hfpwallet/pay033"
	data = service.PayData(&data, 1800)
	Encrypt, errs := rsa.PayVerifyRsa(&data)
	if errs != nil {
		return "", errs
	}
	response, errs := service.PostData("hfPayRequest", Encrypt)
	if response.Code != 200 {
		errs = fmt.Errorf(response.Msg)
		return "", errs
	}
	HfpayOrderResult := service.JsonOrderResultData(response)
	if HfpayOrderResult.RespCode == "C00000" {
		return HfpayOrderResult.PayUrl, nil
	} else {
		errs = fmt.Errorf(HfpayOrderResult.RespDesc)
		return "", errs
	}
}

func (s *WalletService) BalanceWallet(userCustId string, acctId string) (string, int64, error) {
	data := entity.Pay{
		UserCustId: userCustId,
		AcctId:     acctId,
	}
	data.Url = "alse/qry016"
	data = service.PayData(&data)
	Encrypt, errs := rsa.PayVerifyRsa(&data)
	if errs != nil {
		return "", 0, errs
	}
	response, errs := service.PostData("hfPayRequest", Encrypt)
	if response.Code != 200 {
		errs = fmt.Errorf(response.Msg)
		return "", 0, errs
	}
	hfPayResult := service.JsonHfResultData(response)
	if hfPayResult.RespCode == "C00000" {
		return fmt.Sprintf("%.2f", hfPayResult.Balance), 603, nil
	} else {
		errs = fmt.Errorf(hfPayResult.RespDesc)
		return "", 0, errs
	}
}

func (s *WalletService) GoodsPay(price float64, orderNo string, userCustId string, userId string, userName string, idCard string, expTime int) (string, error) {
	payMoney := fmt.Sprintf("%.2f", price) //开户金额
	divDetails := entity.DivDetails{
		DivCustId:   game.Conf.GameConfig["pay_wallet"]["value"].(map[string]any)["mer_cust_id"].(string),
		DivAcctId:   game.Conf.GameConfig["pay_wallet"]["value"].(map[string]any)["div_acct_id"].(string),
		DivAmt:      payMoney,
		RiskDivType: 1,
	}
	var divDetailsArr []entity.DivDetails
	divDetailsArr = append(divDetailsArr, divDetails)
	divDetailsJson, _ := json.Marshal(divDetailsArr)
	objectInfo, _ := json.Marshal(entity.ObjectInfo{
		MarketType: 1,
	})
	data := entity.Pay{
		OrderId:    orderNo,
		UserCustId: userCustId,
		DivType:    0,
		DivDetails: string(divDetailsJson),
		TransAmt:   payMoney,
		Extension:  "goods_order",
		GoodsDesc:  "商品",
		ObjectInfo: string(objectInfo),
		UserName:   userName,
		IdCardType: 10,
		IdCard:     idCard,
		MerPriv:    userId, //商户私有
	}
	data.Url = "hfpwallet/pay033"
	data = service.PayData(&data, expTime)
	Encrypt, errs := rsa.PayVerifyRsa(&data)
	if errs != nil {
		return "", errs
	}
	response, errs := service.PostData("hfPayRequest", Encrypt)
	if response.Code != 200 {
		errs = fmt.Errorf(response.Msg)
		return "", errs
	}
	HfpayOrderResult := service.JsonOrderResultData(response)
	if HfpayOrderResult.RespCode == "C00000" {
		return HfpayOrderResult.PayUrl, nil
	} else {
		errs = fmt.Errorf(HfpayOrderResult.RespDesc)
		return "", errs
	}
}
func (s *WalletService) GoodsAliPay(uid uint, price float64, orderNo string, expTime int64, method string) (string, error) {
	payMoney := fmt.Sprintf("%.2f", price) //开户金额
	client, err := service.AliPay(method)
	if err != nil {
		return "", err
	}
	var urlStr string
	values := url.Values{}
	values.Add("uid", fmt.Sprintf("%d", uid))
	values.Add("module", "goods_order")
	values.Add("method", method)
	if method == "app" {
		var p = alipay.TradeAppPay{}
		p.OutTradeNo = orderNo
		p.TotalAmount = payMoney
		p.Subject = "测试-商品"
		p.PassbackParams = values.Encode()
		p.TimeExpire = utils.TimeAsDate(expTime)
		p.NotifyURL = config.Conf.Alipay.CallbackURL
		urlStr, err = client.TradeAppPay(p)
	} else {
		var p = alipay.TradeWapPay{}
		p.OutTradeNo = orderNo
		p.TotalAmount = payMoney
		p.Subject = "测试-商品"
		p.ProductCode = "QUICK_WAP_WAY"
		//params := map[string]any{
		//	"uid":    uid,
		//	"module": "goods_order",
		//	"method": method,
		//}
		//jsonParam, _ := json.Marshal(params)
		//p.PassbackParams = string(jsonParam)
		p.PassbackParams = values.Encode()
		p.TimeExpire = utils.TimeAsDate(expTime)
		p.NotifyURL = config.Conf.Alipay.CallbackURL
		var Url *url.URL
		Url, err = client.TradeWapPay(p)
		urlStr = Url.String()
	}
	if err != nil {
		return "", err
	}
	return urlStr, nil
}

func (s *WalletService) MarketPay(price float64, orderNo string, userCustId string, userId string, userName string, idCard string, expTime int) (string, error) {
	payMoney := fmt.Sprintf("%.2f", price) //开户金额
	objectInfo, _ := json.Marshal(entity.ObjectInfo{
		MarketType: 2,
	})
	data := entity.Pay{
		OrderId:    orderNo,
		UserCustId: userCustId,
		DivType:    1,
		DivDetails: "",
		TransAmt:   payMoney,
		Extension:  "market_order",
		GoodsDesc:  "市场商品",
		ObjectInfo: string(objectInfo),
		UserName:   userName,
		IdCardType: 10,
		IdCard:     idCard,
		MerPriv:    userId, //商户私有
	}
	data.Url = "hfpwallet/pay033"
	data = service.PayData(&data, expTime)
	Encrypt, errs := rsa.PayVerifyRsa(&data)
	if errs != nil {
		return "", errs
	}
	response, errs := service.PostData("hfPayRequest", Encrypt)
	if response.Code != 200 {
		errs = fmt.Errorf(response.Msg)
		return "", errs
	}
	HfpayOrderResult := service.JsonOrderResultData(response)
	if HfpayOrderResult.RespCode == "C00000" {
		return HfpayOrderResult.PayUrl, nil
	} else {
		errs = fmt.Errorf(HfpayOrderResult.RespDesc)
		return "", errs
	}
}

func (s *WalletService) VipPay(price float64, orderNo string, userCustId string, userId string, userName string, idCard string, expTime int) (string, error) {
	payMoney := fmt.Sprintf("%.2f", price) //开户金额
	divDetails := entity.DivDetails{
		DivCustId:   game.Conf.GameConfig["pay_wallet"]["value"].(map[string]any)["mer_cust_id"].(string),
		DivAcctId:   game.Conf.GameConfig["pay_wallet"]["value"].(map[string]any)["div_acct_id"].(string),
		DivAmt:      payMoney,
		RiskDivType: 1,
	}
	var divDetailsArr []entity.DivDetails
	divDetailsArr = append(divDetailsArr, divDetails)
	divDetailsJson, _ := json.Marshal(divDetailsArr)
	objectInfo, _ := json.Marshal(entity.ObjectInfo{
		MarketType: 1,
	})
	data := entity.Pay{
		OrderId:    orderNo,
		UserCustId: userCustId,
		DivType:    0,
		DivDetails: string(divDetailsJson),
		TransAmt:   payMoney,
		Extension:  "vip_order",
		GoodsDesc:  "月卡",
		ObjectInfo: string(objectInfo),
		UserName:   userName,
		IdCardType: 10,
		IdCard:     idCard,
		MerPriv:    userId, //商户私有
	}
	data.Url = "hfpwallet/pay033"
	data = service.PayData(&data, expTime)
	Encrypt, errs := rsa.PayVerifyRsa(&data)
	if errs != nil {
		return "", errs
	}
	response, errs := service.PostData("hfPayRequest", Encrypt)
	if response.Code != 200 {
		errs = fmt.Errorf(response.Msg)
		return "", errs
	}
	HfpayOrderResult := service.JsonOrderResultData(response)
	if HfpayOrderResult.RespCode == "C00000" {
		return HfpayOrderResult.PayUrl, nil
	} else {
		errs = fmt.Errorf(HfpayOrderResult.RespDesc)
		return "", errs
	}
}

func (s *WalletService) MyWallet(ctx context.Context, userCustId string) (string, error) {
	data := entity.Pay{
		OrderId:    fmt.Sprintf("NTM%s%s", utils.TimeOrDateAsYear(0, "", "YmdHis"), utils.MathInviteCode(15)),
		UserCustId: userCustId,
	}
	data.Url = "hfpwallet/w00004"
	data = service.PayData(&data)
	Encrypt, errs := rsa.PayVerifyRsa(&data)
	if errs != nil {
		return "", errs
	}
	response, errs := service.PostData("hfPayRequest", Encrypt)
	if response.Code != 200 {
		errs = fmt.Errorf(response.Msg)
		return "", errs
	}
	hfPayResult := service.JsonOrderResultData(response)
	if hfPayResult.RespCode == "C00000" {
		return hfPayResult.RedirectUrl, nil
	} else {
		errs = fmt.Errorf(hfPayResult.RespDesc)
		return "", errs
	}
}

func NewWalletService(r *repo.Manager) *WalletService {
	return &WalletService{
		userDao: dao.NewUserDao(r),
	}
}
